package com.carr.controller;

import com.carr.api.dto.ActCurrentTaskDto;
import com.carr.api.dto.ActHistoryTaskDto;
import com.carr.common.constant.TaskConstant;
import org.activiti.engine.HistoryService;
import org.activiti.engine.ManagementService;
import org.activiti.engine.TaskService;
import org.activiti.engine.history.HistoricTaskInstance;
import org.activiti.engine.history.HistoricTaskInstanceQuery;
import org.activiti.engine.task.NativeTaskQuery;
import org.activiti.engine.task.Task;
import org.springframework.beans.BeanUtils;
import org.springframework.web.bind.annotation.*;

import java.lang.reflect.InvocationTargetException;
import java.util.*;

@RestController
@RequestMapping("/task")
public class TaskController {
    private final TaskService taskService;
    private final ManagementService managementService;
    private final HistoryService historyService;

    public TaskController(TaskService taskService, ManagementService managementService, HistoryService historyService) {
        this.taskService = taskService;
        this.managementService = managementService;
        this.historyService = historyService;
    }

    @GetMapping("/current/list")
    public Object currentTaskList(@RequestParam(value = "isLinkUp") Boolean isLinkUp,
                                  @RequestParam(value = "start") int start,
                                  @RequestParam(value = "length") int length) {
        String sql = "SELECT * FROM " + managementService.getTableName(Task.class) + " T WHERE 1=1";
        String countSql = "SELECT count(*) FROM " + managementService.getTableName(Task.class) + " T WHERE 1=1";
        if (Objects.nonNull(isLinkUp)) {
            if (isLinkUp) {
                sql += " and task_def_key_ = #{taskDefKey}";
                countSql += " and task_def_key_ = #{taskDefKey}";
            } else {
                sql += " and task_def_key_ != #{taskDefKey}";
                countSql += " and task_def_key_ != #{taskDefKey}";
            }
        }

        long total = taskService.createNativeTaskQuery().sql(countSql)
                .parameter("taskDefKey", TaskConstant.TASK_CATE_LINK_UP)
                .count();

        sql += " order by create_time_ desc";
        sql += " limit #{start},#{length}";


        NativeTaskQuery nativeTaskQuery = taskService.createNativeTaskQuery();
        List<Task> queryList = nativeTaskQuery.sql(sql)
                .parameter("taskDefKey", TaskConstant.TASK_CATE_LINK_UP)
                .parameter("start", start)
                .parameter("length", length)
                .list();
        List<ActCurrentTaskDto> list = new ArrayList<>();
        queryList.forEach(item -> {
            ActCurrentTaskDto taskDto = new ActCurrentTaskDto();
            BeanUtils.copyProperties(item, taskDto);
            list.add(taskDto);
        });


        HashMap<String, Object> map = new HashMap<>();
        map.put("recordsTotal", total);
        map.put("recordsFiltered", total);
        map.put("data", list);
        return map;
    }

    @GetMapping("/his/list")
    public Object hisTaskList(@RequestParam(value = "isLinkUp") Boolean isLinkUp,
                                  @RequestParam(value = "start") int start,
                                  @RequestParam(value = "length") int length) {

        HistoricTaskInstanceQuery taskQuery = historyService.createHistoricTaskInstanceQuery();
        long count = taskQuery.count();
        List<HistoricTaskInstance> queryList = taskQuery.listPage(start,length);
        List<ActHistoryTaskDto> list = new ArrayList<>(64);
        queryList.forEach(i -> {
            ActHistoryTaskDto taskVO = new ActHistoryTaskDto();
            try {
                org.apache.commons.beanutils.BeanUtils.copyProperties(taskVO, i);
                list.add(taskVO);
            } catch (IllegalAccessException | InvocationTargetException e) {
                e.printStackTrace();
            }
        });

        HashMap<String, Object> map = new HashMap<>();
        map.put("recordsTotal", count);
        map.put("recordsFiltered", count);
        map.put("data", list);
        return map;
    }

}
